package org.spring.bean.factory.config;

import com.sun.istack.internal.Nullable;
import org.spring.bean.factory.BeanFactory;
import org.spring.bean.factory.InitializingBean;

/**
 * 为共享 bean 实例定义注册表的接口。
 * 可以通过 {@link BeanFactory} 实现来实现，以便以统一的方式公开它们的单例管理设施。
 *
 * <p> {@link ConfigurableBeanFactory} 接口扩展了这个接口。
 *
 * @author 李坤
 * @date 2022/4/20 10:38
 */
public interface SingletonBeanRegistry {

    /**
     * 在给定的 bean 名称下，在 bean 注册表中将给定的现有对象注册为单例。
     * <p>
     * 给定的实例应该被完全初始化；注册表不会执行任何初始化回调（特别是，它不会调用 {@link InitializingBean#afterPropertiesSet()} 方法）。
     * 给定的实例也不会收到任何销毁回调（如 {@link DisposableBean#destroy()} 方法）。
     * <p>
     * 在完整的 BeanFactory 中运行时：<b>如果您的 bean 应该接收初始化和或销毁回调，则注册一个 bean 定义而不是现有实例<b>
     * <p>
     * 通常在注册表配置期间调用，但也可用于单例的运行时注册。
     * 因此，注册表实现应该同步单例访问；如果它支持 BeanFactory 的单例延迟初始化，它无论如何都必须这样做。
     *
     * @param beanName        bean 的名字
     * @param singletonObject 现有的单例对象
     *
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     * @see org.springframework.beans.factory.DisposableBean#destroy
     * @see org.springframework.beans.factory.support.BeanDefinitionRegistry#registerBeanDefinition
     */
    void registerSingleton(String beanName, Object singletonObject);

    /**
     * 返回在给定名称下注册的（原始）单例对象。
     * <p>
     * 只检查已经实例化的单例；不会为尚未实例化的单例 bean 定义返回对象。
     * <p>
     * 此方法的主要目的是访问手动注册的单例（参见 {@link #registerSingleton(String, Object)}）。
     * 也可用于以原始方式访问由已创建的 BeanDefinition 定义的单例。
     * <p><b>注意：<b> 此查找方法不知道 FactoryBean 前缀或别名。
     * 在获取单例实例之前，您需要先解析规范的 bean 名称。
     *
     * @param beanName 要查找的 bean 的名称
     *
     * @return 注册的单例对象，如果没有找到则为 {@code null}
     *
     * @see ConfigurableListableBeanFactory#getBeanDefinition
     */
    @Nullable
    Object getSingleton(String beanName);

}
